home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 729 / dsound / source / dsound.c next >
C/C++ Source or Header  |  1995-03-18  |  18KB  |  679 lines

  1.  
  2. /**************************************************************************/
  3. /*                 DSound V1.20                  */
  4. /*     Copyright 1991-1992 by Dave Schreiber, All Rights Reserved      */
  5. /*                                      */
  6. /* To compile:                                  */
  7. /*    lc -Lcd -v -tr DSound Play Mem                      */
  8. /*  or                                      */
  9. /*    lmk                                  */
  10. /*                                      */
  11. /* Revision history:                              */
  12. /*    V1.20  - Added the ability to stop DSound by typing CTRL-C, and      */
  13. /*           added the switch '-w', which keeps the DSound window from  */
  14. /*           opening.                           */
  15. /*    V1.10  - Added the ability to play a sound sample repeatedly (in a  */
  16. /*           loop).                              */
  17. /*           July 11, 1992                          */
  18. /*    V1.00  - Added a new module (Mem.c) which allows a sample to be     */
  19. /*           loaded entirely into memory, so samples can be played from */
  20. /*           floppy disk without first copying to a hard or RAM drive.  */
  21. /*           DSound also can now play a single channel of a stereo      */
  22. /*           out of two speakers.  The small window, used to let the      */
  23. /*           user abort a playing sample, as been redone (DSound also   */
  24. /*           now responds instantly when the user clicks on the Close   */
  25. /*           gadget).  DSound now checks a given 8SVX sample to make      */
  26. /*           sure that it is actually a valid sample.  Finally, DSound  */
  27. /*           has been made pure (residentiable).                        */
  28. /*           Second release (April 16, 1992)                            */
  29. /*    V0.94a - Can now play a mono sample out of both speakers at the      */
  30. /*           same time (using the -2 switch).                           */
  31. /*           March 27, 1992 (a little later)                            */
  32. /*    V0.93a - Now handles stereo sound samples.  Either the right or      */
  33. /*           left, or both, stereo channels can be played.  Also split  */
  34. /*           off the code that actually plays the sound sample into a   */
  35. /*           separate source file (Play.c).                             */
  36. /*           March 27, 1992                          */
  37. /*    V0.92a - Now gets the length of the sound sample from the head of   */
  38. /*           the BODY chunk, instead of the VHDR (a workaround to a bug */
  39. /*           in the Perfect Sound software that would sometimes store   */
  40. /*           an incorrect length in the VHDR chunk of a sound sample).  */
  41. /*           November 4, 1991                       */
  42. /*    V0.91a - First release (September 11, 1991)                         */
  43. /**************************************************************************/
  44.  
  45. #include <exec/types.h>
  46. #include <exec/exec.h>
  47. #include <devices/audio.h>
  48. #include <dos/dos.h>
  49. #include <intuition/intuition.h>
  50. #include <intuition/intuitionbase.h>
  51. #include <graphics/gfxbase.h>
  52. #include <stdlib.h>
  53. #include <stdio.h>
  54.  
  55. #include "dsound.h"
  56.  
  57. #include <proto/intuition.h>
  58. #include <proto/exec.h>
  59. #include <proto/dos.h>
  60.  
  61. char filename[140];
  62.  
  63. #define DEF_BUF_SIZE 30000
  64.  
  65. void InterpretArgs(int argc,char *argv[]);
  66. BOOL noFilter=FALSE;
  67. UBYTE volume=0;
  68. UWORD speed=0;
  69. ULONG bufSize=DEF_BUF_SIZE;
  70.  
  71. void filter_on(void);
  72. void filter_off(void);
  73.  
  74. char *version="$VER: DSound V1.20 (23.8.92)";
  75. char *copyright="Copyright 1991-1992 by Dave Schreiber, All Rights Reserved";
  76.  
  77. struct IntuitionBase *IntuitionBase=NULL;
  78. struct GfxBase *GfxBase=NULL;
  79.  
  80. struct Window *window=NULL;
  81.  
  82. BPTR file=NULL;
  83.  
  84. channel audioChannel=UNSPECIFIED;
  85. BOOL bothChan=FALSE;
  86. BOOL readAll=FALSE;
  87. BOOL loop=FALSE;
  88.  
  89. /*The window definition*/
  90. struct NewWindow newWindow = {
  91.     124,31,
  92.     250,56,
  93.     0,1,
  94.     CLOSEWINDOW,
  95.     SMART_REFRESH|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE,
  96.     NULL,
  97.     NULL,
  98.     "DSound V1.20",
  99.     NULL,
  100.     NULL,
  101.     5,5,
  102.     640,200,
  103.     WBENCHSCREEN
  104. };
  105.  
  106. /*This determines whether or not the window will be opened*/
  107. BOOL openTheWdw=TRUE;
  108. ULONG signalMask=SIGBREAKF_CTRL_C;
  109.  
  110. main(int argc,char *argv[])
  111. {
  112.    struct Voice8Header vhdr;
  113.    UBYTE foo2[5];
  114.    UBYTE foo[5];
  115.    ULONG chan;
  116.    ULONG sampleLength;
  117.    ULONG lock;
  118.    char *chanStr;
  119.  
  120.    filename[0]=NULL;
  121.  
  122.    /*Get and interpret the command-line arguments*/
  123.    InterpretArgs(argc,argv);
  124.  
  125.    /*Exit if there was no sound sample specified*/
  126.    if(filename[0]==NULL)
  127.    {
  128.       WriteMsg("Please specify the name of a sound sample\n");
  129.       cleanup(75);
  130.    }
  131.  
  132.    /*Open the file*/
  133.    file=Open(filename,MODE_OLDFILE);
  134.    if(file==NULL)
  135.    {
  136.       WriteMsg("Couldn't open the file\n");
  137.       cleanup(100);
  138.    }
  139.  
  140.    /*If the user hasn't told us not to open the window*/
  141.  
  142.    if(openTheWdw)
  143.    {
  144.       /*Open libraries*/
  145.       GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
  146.       IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
  147.  
  148.       if(GfxBase==NULL || IntuitionBase==NULL)
  149.       {
  150.      WriteMsg("A shared library could not be opened\n");
  151.      cleanup(50);
  152.       }
  153.  
  154.       /*Get the size of the title bar font in a rather illegal way        */
  155.       /*Note:  programmers at C= should put a GetDefTitleBarFontHeight()    */
  156.       /*function into Intuition before complaining to me about the following*/
  157.       /*code.                                    */
  158.  
  159.       lock=LockIBase(0L);
  160.       newWindow.Height=IntuitionBase->ActiveScreen->Font->ta_YSize+3;
  161.       UnlockIBase(lock);
  162.  
  163.       window=OpenWindow(&newWindow);
  164.  
  165.       if(window==NULL)
  166.      cleanup(110);
  167.       signalMask|=1<<window->UserPort->mp_SigBit;
  168.    }
  169.  
  170.    /*Read the header*/
  171.    Read(file,foo,4);
  172.    Seek(file,4,OFFSET_CURRENT);
  173.    Read(file,foo2,4);
  174.  
  175.    foo[4]=foo2[4]=NULL;
  176.  
  177.    /*Check the header's validity, more or less*/
  178.    if((strcmp(foo,"FORM")!=0) || (strcmp(foo2,"8SVX")!=0))
  179.    {
  180.       WriteMsg("Not a valid IFF 8SVX sound sample file.\n");
  181.       cleanup(120);
  182.    }
  183.  
  184.    if(strcmp(FindChunk(file,"VHDR"),"VHDR")!=0)
  185.    {
  186.       WriteMsg("Couldn't find the 8SVX header (VHDR).\n");
  187.       cleanup(130);
  188.    }
  189.  
  190.    /*Skip past the chunk size*/
  191.    Seek(file,4,OFFSET_CURRENT);
  192.  
  193.    /*Get the VHDR*/
  194.    Read(file,&vhdr,sizeof(struct Voice8Header));
  195.  
  196.    /*Check for compression*/
  197.    if(vhdr.sCompression!=0)
  198.    {
  199.       WriteMsg("Can't play a compressed sample!\n");
  200.       cleanup(400);
  201.    }
  202.  
  203.    /*Get the CHAN chunk (which will tell us if the sample is stereo, or,*/
  204.    /*if it is mono, which speaker it should be played out of*/
  205.    chanStr=FindChunk(file,"CHAN");
  206.    if(strcmp(chanStr,"CHAN")==0)
  207.    {
  208.       /*Skip past chunk size*/
  209.       Seek(file,4,OFFSET_CURRENT);
  210.       Read(file,&chan,sizeof(long));
  211.  
  212.       /*The information we're looking for consists of one longword*/
  213.       switch(chan)
  214.       {
  215.      case 2:  /*Mono sample, left speaker*/
  216.         if(bothChan)
  217.            /*Play out of both channels if -2 used*/
  218.            audioChannel=MONO_BOTH;
  219.         else
  220.            if(audioChannel==UNSPECIFIED)
  221.           audioChannel=MONO_LEFT;
  222.         break;
  223.      case 4:  /*Mono sample, right speaker*/
  224.         if(bothChan)
  225.            /*Play out of both channels if -2 used*/
  226.            audioChannel=MONO_BOTH;
  227.         else
  228.            if(audioChannel==UNSPECIFIED)
  229.           audioChannel=MONO_RIGHT;
  230.         break;
  231.      case 6:     /*Stereo*/
  232.         switch(audioChannel)
  233.         {
  234.            /*This reconciles a user's choice with the fact that the*/
  235.            /*sample is in stereo*/
  236.  
  237.            /*Play left stereo channel*/
  238.            case MONO_LEFT:
  239.           if(bothChan)
  240.              audioChannel=STEREO_LEFT_BOTH;
  241.           else
  242.              audioChannel=STEREO_LEFT;
  243.           break;
  244.  
  245.            /*Play right stereo channel*/
  246.            case MONO_RIGHT:
  247.           if(bothChan)
  248.              audioChannel=STEREO_RIGHT_BOTH;
  249.           else
  250.              audioChannel=STEREO_RIGHT;
  251.           break;
  252.  
  253.            /*Play both channels*/
  254.            case UNSPECIFIED:
  255.           audioChannel=STEREO;
  256.           break;
  257.         }
  258.         break;
  259.       }
  260.  
  261.       /*Find the start of the BODY chunk*/
  262.       chanStr=FindChunk(file,"BODY");
  263.    }
  264.    else
  265.    {
  266.       chan=0;
  267.       if(bothChan)
  268.      audioChannel=MONO_BOTH;
  269.    }
  270.  
  271.    if(strcmp(chanStr,"BODY")!=0)
  272.    {
  273.       WriteMsg("Couldn't find body of sample.\n");
  274.       cleanup(140);
  275.    }
  276.  
  277.    if(noFilter)
  278.       filter_off();
  279.  
  280.    /*Get the length of the sample*/
  281.    Read(file,(char *)&sampleLength,4);
  282.  
  283.    SetSignal(0,0);
  284.  
  285.    /*Play the sample by choosing the appropriate player function*/
  286.    switch(audioChannel)
  287.    {
  288.       case MONO_LEFT:
  289.       case MONO_RIGHT:
  290.       case UNSPECIFIED:
  291.      /*Simple mono playback*/
  292.      playMonoSample(file,audioChannel,&vhdr,sampleLength);
  293.      break;
  294.       case MONO_BOTH:
  295.      /*Mono playback using both speakers*/
  296.      playMonoTwice(file,audioChannel,&vhdr,sampleLength);
  297.      break;
  298.       case STEREO_RIGHT:
  299.      /*Right stereo channel*/
  300.      audioChannel=MONO_RIGHT;
  301.      Seek(file,sampleLength/2,OFFSET_CURRENT);
  302.      playMonoSample(file,audioChannel,&vhdr,sampleLength/2);
  303.      break;
  304.       case STEREO_RIGHT_BOTH:
  305.      /*Right stereo channel out of both speakers*/
  306.      audioChannel=MONO_RIGHT;
  307.      Seek(file,sampleLength/2,OFFSET_CURRENT);
  308.      playMonoTwice(file,audioChannel,&vhdr,sampleLength/2);
  309.      break;
  310.       case STEREO_LEFT:
  311.      /*Left stereo channel*/
  312.      audioChannel=MONO_LEFT;
  313.      playMonoSample(file,audioChannel,&vhdr,sampleLength/2);
  314.      break;
  315.       case STEREO_LEFT_BOTH:
  316.      /*Left stereo channel out of both speakers*/
  317.      audioChannel=MONO_LEFT;
  318.      playMonoTwice(file,audioChannel,&vhdr,sampleLength/2);
  319.      break;
  320.       case STEREO:
  321.      /*Stereo sample (both channels)*/
  322.      playStereoSample(file,audioChannel,&vhdr,sampleLength/2,filename);
  323.      break;
  324.    }
  325.  
  326.    if(noFilter)
  327.       filter_on();
  328.  
  329.    /*Free allocated resources and exit*/
  330.    cleanup(0);
  331. }
  332.  
  333.  
  334.  
  335. /* Get an audio channel */
  336. struct IOAudio *GetAudioChannel(ULONG bufferSize,UBYTE *allocationMap)
  337. {
  338.    struct IOAudio *aIOB;
  339.    void *audioBuf;
  340.    struct Port *aPort;
  341.  
  342.    aPort=(struct Port *)CreatePort("dsound",0);
  343.    if(aPort==NULL)
  344.       return(NULL);
  345.  
  346.    /* Allocate the chip memory buffer for the channel */
  347.    audioBuf=(void *)AllocMem(bufferSize,MEMF_CHIP);
  348.    if(audioBuf==NULL)
  349.    {
  350.       DeletePort(aPort);
  351.       return(NULL);
  352.    }
  353.  
  354.    /* Allocate an IOAudio structure*/
  355.    aIOB=(struct IOAudio *)AllocMem(sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
  356.    if(aIOB==NULL)
  357.    {
  358.       DeletePort(aPort);
  359.       FreeMem(audioBuf,bufferSize);
  360.       return(NULL);
  361.    }
  362.  
  363.    /* Set up the IOAudio to allocate the command channel */
  364.    aIOB->ioa_Request.io_Message.mn_Node.ln_Pri=0;
  365.    aIOB->ioa_Request.io_Message.mn_ReplyPort=aPort;
  366.  
  367.    aIOB->ioa_Data=allocationMap;
  368.    aIOB->ioa_Length=4;
  369.    aIOB->ioa_Request.io_Command=ADCMD_ALLOCATE;
  370.  
  371.    /*Open the audio device*/
  372.    OpenDevice("audio.device",0,(struct IORequest *)aIOB,0);
  373.  
  374.  
  375.    if(aIOB->ioa_AllocKey==0)
  376.    {  /*There was an error*/
  377.       DeletePort(aPort);
  378.       FreeMem(audioBuf,bufferSize);
  379.       FreeMem(aIOB,sizeof(struct IOAudio));
  380.       return(NULL);
  381.    }
  382.    else
  383.    {
  384.       /* Set up the IOAudio for writes */
  385.       aIOB->ioa_Request.io_Command=CMD_WRITE;
  386.       aIOB->ioa_Request.io_Flags=ADIOF_PERVOL;
  387.       aIOB->ioa_Data=audioBuf;
  388.       aIOB->ioa_Length=bufferSize;
  389.       return(aIOB);
  390.    }
  391. }
  392.  
  393. /* Free an allocated audio channel */
  394. void FreeAudioChannel(struct IOAudio *aIOB)
  395. {
  396.    if(aIOB==NULL)
  397.       return;
  398.  
  399.    /* Free the audi obuffer */
  400.    if(aIOB->ioa_Data!=NULL)
  401.       FreeMem(aIOB->ioa_Data,aIOB->ioa_Length);
  402.  
  403.    /* Free the audio channel */
  404.    aIOB->ioa_Request.io_Command=ADCMD_FREE;
  405.    BeginIO((struct IORequest *)aIOB);
  406.    WaitIO((struct IORequest *)aIOB);
  407.    DeletePort(aIOB->ioa_Request.io_Message.mn_ReplyPort);
  408.  
  409.    /* Close the audio channel */
  410.    CloseDevice((struct IORequest *)aIOB);
  411.  
  412.    /* Free the IOAudio structure */
  413.    FreeMem(aIOB,sizeof(struct IOAudio));
  414.    return;
  415. }
  416.  
  417. /* Initialize an IOAudio's volume, period, and set the number of cycles */
  418. /* to one */
  419. void InitAudioChannel(struct IOAudio *aIOB,UWORD volume,UWORD period)
  420. {
  421.    aIOB->ioa_Period=period;
  422.    aIOB->ioa_Volume=volume;
  423.    aIOB->ioa_Cycles=1;
  424.    return;
  425. }
  426.  
  427. /* Duplicate an IOAudio structure */
  428. struct IOAudio *DuplicateAudioChannel(struct IOAudio *OrigIOB)
  429. {
  430.    struct IOAudio *aIOB;
  431.    void *audioBuf;
  432.  
  433.    if(OrigIOB==NULL)
  434.       return(NULL);
  435.  
  436.    /* Allocate the alternate buffer */
  437.    audioBuf=(void *)AllocMem(OrigIOB->ioa_Length,MEMF_CHIP);
  438.    if(audioBuf==NULL)
  439.       return(NULL);
  440.  
  441.    /*Allocate the IOAudio structure*/
  442.    aIOB=(struct IOAudio *)AllocMem(sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
  443.    if(aIOB==NULL)
  444.    {
  445.       FreeMem(audioBuf,OrigIOB->ioa_Length);
  446.       return(NULL);
  447.    }
  448.  
  449.    /*Copy the original IOAudio's contents to the new one*/
  450.    CopyMem(OrigIOB,aIOB,sizeof(struct IOAudio));
  451.  
  452.    /*Except for the buffer pointer, of course*/
  453.    aIOB->ioa_Data=audioBuf;
  454.  
  455.    return(aIOB);
  456. }
  457.  
  458. /*Delete a duplicated IOAudio*/
  459. void DeleteDuplication(struct IOAudio *aIOB)
  460. {
  461.    if(aIOB != NULL)
  462.    {
  463.       /* Free the memory for the buffer and IOAudio */
  464.       if(aIOB->ioa_Data != NULL)
  465.      FreeMem(aIOB->ioa_Data,aIOB->ioa_Length);
  466.       FreeMem(aIOB,sizeof(struct IOAudio));
  467.    }
  468.    return;
  469. }
  470.  
  471. /* Load an IOAudio's buffer from an open file */
  472. ULONG LoadAudioBuffer(BPTR file,struct IOAudio *aIOB,ULONG toRead)
  473. {
  474.    if(toRead==0)
  475.       return(0);
  476.  
  477.    if(file==0L)
  478.       getLeft(aIOB->ioa_Data);
  479.    else if(file==4L)
  480.       getRight(aIOB->ioa_Data);
  481.    else
  482.       aIOB->ioa_Length=Read(file,aIOB->ioa_Data,toRead);
  483.    return(aIOB->ioa_Length);
  484. }
  485.  
  486. /*Find the beginning of an IFF chunk.  This routine will search for that*/
  487. /*chunk's name, and if found, will leave the file cursor at the chunk size*/
  488. /*field.  If the chunk isn't found, the file cursor will be left at the*/
  489. /*size field of the BODY chunk, if there was one*/
  490. char *FindChunk(BPTR file,char *string)
  491. {
  492.    static char buf[5];
  493.    long len,actLen;
  494.    buf[4]=NULL;
  495.  
  496.    actLen=Read(file,buf,4);
  497.    while(strcmp(string,buf)!=0 && strcmp(buf,"BODY")!=0 && actLen > 0)
  498.    {
  499.       Read(file,(char *)&len,4);
  500.       Seek(file,len,OFFSET_CURRENT);
  501.       actLen=Read(file,buf,4);
  502.    }
  503.    return(buf);
  504. }
  505.  
  506. /* Interpret the command line arguments */
  507. void InterpretArgs(int argc,char *argv[])
  508. {
  509.    int i;
  510.  
  511.    for(i=1;i<argc;i++)
  512.    {
  513.       if(argv[i][0]=='-')
  514.      switch(argv[i][1])
  515.      {
  516.         /* Read the entire sample into memory before playing */
  517.         case 'm':
  518.         case 'M':
  519.            readAll=TRUE;
  520.            break;
  521.  
  522.         /* Use the left channel */
  523.         case 'l':
  524.         case 'L':
  525.            audioChannel=MONO_LEFT;
  526.            break;
  527.  
  528.         /* Use the right channel */
  529.         case 'r':
  530.         case 'R':
  531.            audioChannel=MONO_RIGHT;
  532.            break;
  533.  
  534.         /*Play a mono sample out of both speakers*/
  535.         case '2':
  536.            bothChan=TRUE;
  537.            break;
  538.  
  539.         /* Switch off the low-pass filter while the sample is playing */
  540.         case 'f':
  541.         case 'F':
  542.            noFilter=TRUE;
  543.            break;
  544.  
  545.         /* Play a sample at a given speed */
  546.         case 's':
  547.         case 'S':
  548.            speed=atol(&argv[i][2]);
  549.            if(speed > 28000)
  550.           speed=0;
  551.            break;
  552.  
  553.         /* The volume at which the sample should be played */
  554.         case 'v':
  555.         case 'V':
  556.            volume=atol(&argv[i][2]);
  557.            if(volume > 64)
  558.           volume=0;
  559.            break;
  560.  
  561.         /* The size of the chip RAM buffers */
  562.         case 'b':
  563.         case 'B':
  564.            bufSize=(atol(&argv[i][2])+1)&(~1);
  565.            if(bufSize==0)
  566.           bufSize=DEF_BUF_SIZE;
  567.            break;
  568.  
  569.         /* Loop the sample */
  570.         case 'o':
  571.         case 'O':
  572.            loop=TRUE;
  573.            break;
  574.  
  575.         case 'w':
  576.         case 'W':
  577.            openTheWdw=FALSE;
  578.            break;
  579.      }
  580.       else if(argv[i][0]=='?')
  581.       {
  582.      /*On-line help*/
  583.      WriteMsg("DSound V1.20 ©1991-1992 by Dave Schreiber\n");
  584.      WriteMsg("Usage:\n");
  585.      WriteMsg("  DSound <options> <filename>\n");
  586.      WriteMsg("Where the options are:\n");
  587.      WriteMsg("  -l -- Play the sample using the left speaker\n");
  588.      WriteMsg("  -r -- Play the sample using the right speaker\n");
  589.      WriteMsg("  -2 -- Play the sample using both speakers\n");
  590.      WriteMsg("  -f -- Shut off the low-pass filter\n");
  591.      WriteMsg("  -m -- Load the entire sample into memory\n");
  592.      WriteMsg("  -o -- Play the sample continuously (loop)\n");
  593.      WriteMsg("  -w -- Do not open the DSound window\n");
  594.      WriteMsg("  -s<speed> -- Play the sample at the given speed (samples/sec)\n");
  595.      WriteMsg("  -v<volume> -- Play the sample at the given volume (0-64)\n");
  596.      WriteMsg("  -b<bufsize> -- Use a buffer of size <bufsize> (default is 30K)\n");
  597.      exit(0);
  598.       }
  599.       else     /*Otherwise, the argument is a filename */
  600.      strcpy(filename,argv[i]);
  601.    }
  602. }
  603.  
  604. /*Switch on the low-pass filter */
  605. void filter_on()
  606. {
  607.    *((char *)0x0bfe001)&=0xFD;
  608. }
  609.  
  610. /*Switch off the low-pass filter*/
  611. void filter_off()
  612. {
  613.    *((char *)0x0bfe001)|=0x02;
  614. }
  615.  
  616. /*Write a message to the CLI*/
  617. void WriteMsg(char *errMsg)
  618. {
  619.    Write(Output(),errMsg,strlen(errMsg));
  620. }
  621.  
  622. /*Take a file handle and that handle's filename, and open that file again*/
  623. /*The position in the second file in set to the position in the first */
  624. /*file (so that the two file handles are essentially identical)*/
  625. /*This requires that the first file was opened in a shared mode, like */
  626. /*MODE_OLDFILE*/
  627. BPTR dupFileHandle(BPTR origFile,char *filename)
  628. {
  629.    BPTR dupFile;
  630.  
  631.    dupFile=Open(filename,MODE_OLDFILE);
  632.  
  633.    if(dupFile==NULL)
  634.       return(NULL);
  635.  
  636.    Seek(dupFile,getPosInFile(origFile),OFFSET_BEGINNING);
  637.    return(dupFile);
  638. }
  639.  
  640. /*Get the current position in a file*/
  641. ULONG getPosInFile(BPTR file)
  642. {
  643.    LONG position;
  644.  
  645.    position=Seek(file,0,OFFSET_CURRENT);
  646.    return((ULONG)position);
  647. }
  648.  
  649. /* Free allocated resources */
  650. void cleanup(int err)
  651. {
  652.    /*If the entire sample was read into memory, this will delete whatever*/
  653.    /*part of the sample still remains in memory*/
  654.    deleteLeft();
  655.    deleteRight();
  656.  
  657.    if(file!=NULL)
  658.       Close(file);
  659.  
  660.    if(window!=NULL)
  661.       CloseWindow(window);
  662.  
  663.    if(GfxBase!=NULL)
  664.       CloseLibrary((struct Library *)GfxBase);
  665.  
  666.    if(IntuitionBase!=NULL)
  667.       CloseLibrary((struct Library *)IntuitionBase);
  668.  
  669.    exit(err);
  670. }
  671.  
  672. #ifdef LATTICE
  673. int CXBRK(void) {return(0);}
  674. int chkabort(void) {return(0);}
  675. #endif
  676.  
  677. /*End of DSound.c*/
  678.  
  679.